import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/services.dart';

import 'src/pangle_platform_interface.dart';
import 'src/models.dart';

/// MethodChannel实现类
class MethodChannelFlutterPangle extends FlutterPanglePlatform {
  @visibleForTesting
  final methodChannel = const MethodChannel('flutter_pangle');
  String? _cachedRegionCode;

  MethodChannelFlutterPangle() : super() {
    // 如果还没有设置实例，则设置为当前实例
    try {
      // 尝试访问instance，如果为null会抛出异常
      FlutterPanglePlatform.instance;
    } catch (_) {
      // 如果instance未初始化，则设置为当前实例
      FlutterPanglePlatform.instance = this;
    }
    // Preload native region code asynchronously and cache
    methodChannel
        .invokeMethod<String>('getCurrentLanguage')
        .then((value) {
          if (value != null && value.isNotEmpty) {
            _cachedRegionCode = value;
          }
        })
        .catchError((_) {
          // ignore
        });
  }

  @override
  Future<bool> initializeSDK(PAGSSDKConfig config) async {
    final result = await methodChannel.invokeMethod<bool>(
      'initializeSDK',
      config.toMap(),
    );
    return result ?? false;
  }

  @override
  Future<void> setEligibleAudience(bool eligible) async {
    await methodChannel.invokeMethod('setEligibleAudience', {
      'eligible': eligible,
    });
  }

  @override
  Future<void> setContentLanguage(String language) async {
    await methodChannel.invokeMethod('setContentLanguage', {
      'language': language,
    });
  }

  @override
  Future<void> setContentLanguages(List<String> languages) async {
    await methodChannel.invokeMethod('setContentLanguages', {
      'languages': languages,
    });
  }

  @override
  Future<PAGSFeedListResponse> requestFeedList({
    required int index,
    required int count,
  }) async {
    final result = await methodChannel.invokeMethod<Map<dynamic, dynamic>>(
      'requestFeedList',
      {'index': index, 'count': count},
    );
    if (result == null) {
      return PAGSFeedListResponse(
        list: [],
        hasMore: false,
        error: 'Unknown error',
      );
    }
    final normalized = <String, dynamic>{};
    result.forEach((k, v) => normalized[k.toString()] = v);
    return PAGSFeedListResponse.fromMap(normalized);
  }

  @override
  Future<PAGSFeedListResponse> requestFeedListWithFilters({
    required int index,
    required int count,
    List<int>? categoryIds,
    List<int>? shortplayIds,
  }) async {
    final result = await methodChannel
        .invokeMethod<Map<dynamic, dynamic>>('requestFeedListWithFilters', {
          'index': index,
          'count': count,
          'categoryIds': categoryIds,
          'shortplayIds': shortplayIds,
        });
    if (result == null) {
      return PAGSFeedListResponse(
        list: [],
        hasMore: false,
        error: 'Unknown error',
      );
    }
    final normalized = <String, dynamic>{};
    result.forEach((k, v) => normalized[k.toString()] = v);
    return PAGSFeedListResponse.fromMap(normalized);
  }

  @override
  Future<PAGSFeedListResponse> requestPopularDrama({
    required int index,
    required int count,
  }) async {
    final result = await methodChannel.invokeMethod<Map<dynamic, dynamic>>(
      'requestPopularDrama',
      {'index': index, 'count': count},
    );
    if (result == null) {
      return PAGSFeedListResponse(
        list: [],
        hasMore: false,
        error: 'Unknown error',
      );
    }
    final normalized = <String, dynamic>{};
    result.forEach((k, v) => normalized[k.toString()] = v);
    return PAGSFeedListResponse.fromMap(normalized);
  }

  @override
  Future<PAGSFeedListResponse> requestNewFeedList({
    required int index,
    required int count,
  }) async {
    final result = await methodChannel.invokeMethod<Map<dynamic, dynamic>>(
      'requestNewFeedList',
      {'index': index, 'count': count},
    );
    if (result == null) {
      return PAGSFeedListResponse(
        list: [],
        hasMore: false,
        error: 'Unknown error',
      );
    }
    final normalized = <String, dynamic>{};
    result.forEach((k, v) => normalized[k.toString()] = v);
    return PAGSFeedListResponse.fromMap(normalized);
  }

  @override
  Future<PAGSFeedListResponse> requestDramaWithTag({
    required int tag,
    required int index,
    required int count,
  }) async {
    final result = await methodChannel.invokeMethod<Map<dynamic, dynamic>>(
      'requestDramaWithTag',
      {'tag': tag, 'index': index, 'count': count},
    );
    if (result == null) {
      return PAGSFeedListResponse(
        list: [],
        hasMore: false,
        error: 'Unknown error',
      );
    }
    final normalized = <String, dynamic>{};
    result.forEach((k, v) => normalized[k.toString()] = v);
    return PAGSFeedListResponse.fromMap(normalized);
  }

  @override
  Future<List<PAGSCategoryItem>> getCategoryList(String language) async {
    final result = await methodChannel.invokeMethod<List<dynamic>>(
      'getCategoryList',
      {'language': language},
    );
    if (result == null) {
      return [];
    }
    return result
        .map(
          (e) => PAGSCategoryItem.fromMap(
            Map<String, dynamic>.from(
              (e as Map).map((k, v) => MapEntry(k.toString(), v)),
            ),
          ),
        )
        .toList();
  }

  @override
  Future<PAGSFeedListResponse> requestSearchDrama({
    required int index,
    required int count,
    required String keyword,
    required bool isFuzzy,
  }) async {
    final result = await methodChannel.invokeMethod<Map<dynamic, dynamic>>(
      'requestSearchDrama',
      {'index': index, 'count': count, 'keyword': keyword, 'isFuzzy': isFuzzy},
    );
    if (result == null) {
      return PAGSFeedListResponse(
        list: [],
        hasMore: false,
        error: 'Unknown error',
      );
    }
    final normalized = <String, dynamic>{};
    result.forEach((k, v) => normalized[k.toString()] = v);
    return PAGSFeedListResponse.fromMap(normalized);
  }

  @override
  Future<int> checkPlayStatus() async {
    final result = await methodChannel.invokeMethod<int>('checkPlayStatus');
    return result ?? 0; // 0 = unknown, 1 = support, 2 = not support
  }

  @override
  Future<bool> setCollected({
    required bool collected,
    required int shortplayId,
  }) async {
    final result = await methodChannel.invokeMethod<bool>('setCollected', {
      'collected': collected,
      'shortplayId': shortplayId,
    });
    return result ?? false;
  }

  @override
  Future<void> clearLocalCache() async {
    await methodChannel.invokeMethod('clearLocalCache');
  }

  @override
  String getCurrentLanguage() {
    // Return cached native region code if available; fallback to Dart locale country
    if (_cachedRegionCode != null && _cachedRegionCode!.isNotEmpty) {
      return _cachedRegionCode!;
    }
    final locale = WidgetsBinding.instance.platformDispatcher.locale;
    final country = (locale.countryCode ?? '').toUpperCase();
    return country.isEmpty ? 'US' : country;
  }

  @override
  Future<void> warmUpPlayerEngine() async {
    try {
      await methodChannel.invokeMethod('warmUpPlayerEngine');
    } catch (e) {
      // 忽略错误，预热失败不影响正常使用
      debugPrint('Warm up player engine failed: $e');
    }
  }
}
